﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NumericalCalculations
{
    public class Functions
    {
        //Dictionary koji sadrzi pozive
        public static Dictionary<string, f> FunctionsDictionary;


        //metod za punjenje distionary-ja
        public void addFunctions()
        {
            FunctionsDictionary = new Dictionary<string, f>();

        }

        //delegat za dictionary
        public delegate List<QLabValues.IQLabValue> f(List<QLabValues.IQLabValue> o);

        #region Pomocne_Funkcije


        //metod od liste IQLabValuesa vraca listu odgovarajucih enumova- U OVOM TRENUTKU NE TREBA
        //JER SAM NAPRAVIO DONJI METOD TAKO DA NE PRIHVATA ENUM, ALI CE MOZDA ZATREBATI NEKAD
        public List<QLabValues.IQLabValueType> getEnumList(List<QLabValues.IQLabValue> o)
        {
            List<QLabValues.IQLabValueType> res = new List<QLabValues.IQLabValueType>();

            foreach (var curr in o)
            {
                res.Add(curr.getEnumType());
            }

            return res;
         }
        

    

        //metod vraca da li prvi tip moze da se konvertuje u drugi
        //u obzir se uzima da mogu da se dobiju samo naveci moguci tipovi svoje vrste -> Boolean, Char, UInt64, Int64, Float64
        //hijerarhija je sledeca: Boolean, Char, UInt64, Int64, Float64 (boolean i char su na istom nivou hijerarhije)
        //moguce je konvertovati samo nize u vise
        public bool canConvertToEnum(QLabValues.IQLabValue first, QLabValues.IQLabValueType second)
        {
            if (second == QLabValues.IQLabValueType.QBooleanArray)
            {
                if (first.getEnumType() == QLabValues.IQLabValueType.QBooleanArray)
                    return true;
            }
            else if (second == QLabValues.IQLabValueType.QCharArray)
            {
                if (first.getEnumType() == QLabValues.IQLabValueType.QCharArray)
                    return true;
            }
            else if (second == QLabValues.IQLabValueType.QUInt64Array)
            {
                QLabValues.IQLabValueType enumHelp = first.getEnumType();
                if ((enumHelp == QLabValues.IQLabValueType.QCharArray) || 
                    (enumHelp == QLabValues.IQLabValueType.QBooleanArray)||
                    (enumHelp == QLabValues.IQLabValueType.QUInt64Array))
                    return true;
            }
            else if (second == QLabValues.IQLabValueType.QInt64Array)
            {
                QLabValues.IQLabValueType enumHelp = first.getEnumType();
                if ((enumHelp == QLabValues.IQLabValueType.QBooleanArray)||
                    (enumHelp == QLabValues.IQLabValueType.QCharArray)||
                    (enumHelp == QLabValues.IQLabValueType.QUInt64Array)||
                    (enumHelp == QLabValues.IQLabValueType.QInt64Array))
                    return true;
            }
            else if (second == QLabValues.IQLabValueType.QFloat64Array)
            {
                QLabValues.IQLabValueType enumHelp = first.getEnumType();
                if ((enumHelp == QLabValues.IQLabValueType.QBooleanArray) ||
                    (enumHelp == QLabValues.IQLabValueType.QCharArray) ||
                    (enumHelp == QLabValues.IQLabValueType.QUInt64Array) ||
                    (enumHelp == QLabValues.IQLabValueType.QInt64Array) ||
                    (enumHelp == QLabValues.IQLabValueType.QFloat64Array))
                    return true;
            }

            return false;
            

        }


        //Metod koji kaze moze li se svaki element liste konvertovati u neki odredjeni enum
        // koristicemo ga kod fja kako bi dobili kog ce tipa biti rezultat
        //provera ce se vrsiti, tako sto se proverava gornja hijerarhija tipova
        public bool canConvertListToEnum(List<QLabValues.IQLabValue> l, QLabValues.IQLabValueType t)
        {
            bool ind = true;
            foreach (var el in l)
            {
                if (this.canConvertToEnum(el, t) == false)
                {
                    ind = false;
                    break;
                }
            }
            return ind;
        }

        //Napravio sam posebno za svaki tip koji mogu da dobijem, da ne bi morao da pisem dodatne konstruktore
        public bool checkDimensions(Memory_Access.QInt64Array first, Memory_Access.QInt64Array second)
        {
            int[] fd = (int[])first.DimensionSize.Clone();
            int[] sd = (int[])second.DimensionSize.Clone();

            if (fd.Count() != sd.Count())
                return false;
            for (int i = 0; i < fd.Count(); i++)
                if (fd[i] != sd[i])
                    return false;
            return true;
        }

        public bool checkDimensions(Memory_Access.QBooleanArray first, Memory_Access.QBooleanArray second)
        {
            int[] fd = (int[])first.DimensionSize.Clone();
            int[] sd = (int[])second.DimensionSize.Clone();

            if (fd.Count() != sd.Count())
                return false;
            for (int i = 0; i < fd.Count(); i++)
                if (fd[i] != sd[i])
                    return false;
            return true;
        }

        public bool checkDimensions(Memory_Access.QUInt64Array first, Memory_Access.QUInt64Array second)
        {
            int[] fd = (int[])first.DimensionSize.Clone();
            int[] sd = (int[])second.DimensionSize.Clone();

            if (fd.Count() != sd.Count())
                return false;
            for (int i = 0; i < fd.Count(); i++)
                if (fd[i] != sd[i])
                    return false;
            return true;
        }

        public bool checkDimensions(Memory_Access.QFloat64Array first, Memory_Access.QFloat64Array second)
        {
            int[] fd = (int[])first.DimensionSize.Clone();
            int[] sd = (int[])second.DimensionSize.Clone();

            if (fd.Count() != sd.Count())
                return false;
            for (int i = 0; i < fd.Count(); i++)
                if (fd[i] != sd[i])
                    return false;
            return true;
        }

        public bool checkDimensions(Memory_Access.QCharArray first, Memory_Access.QCharArray second)
        {
            int[] fd = (int[])first.DimensionSize.Clone();
            int[] sd = (int[])second.DimensionSize.Clone();

            if (fd.Count() != sd.Count())
                return false;
            for (int i = 0; i < fd.Count(); i++)
                if (fd[i] != sd[i])
                    return false;
            return true;
        }

        #endregion


        public List<QLabValues.IQLabValue> plus(List<QLabValues.IQLabValue>)
        {
            return null;

        }


        
        /*
         public static NDimArrayNamespace.NDimArray<dynamic> test(List<NDimArrayNamespace.NDimArray<dynamic> > abcde)
         {
             Dictionary<string, f> abc = new Dictionary<string, f>();
             abc.Add("a", a);
             object t = abc["a"]("sss");

             //"ime ml fun","ime fun ql"
             return null;
                  
         }

         public static object a(object o)
         {
             return null;
         }*/
    }
}